// -----------------------------
// Author: 		Dhaenens Gert	
// Creation: 	2/26/2015 6:12:16 PM				
// -----------------------------

#include "FilePackage.h"

#include "File.h"

namespace Flow
{

	const UInt32 FilePackage::NameLength = 256;

	FilePackage::FilePackage(const tstring& name, const tstring& path)
		: m_Name(name)
		, m_Path(path)
	{
	}

	FilePackage::~FilePackage()
	{
		for(auto pair : m_Files)
			delete pair.second;
	}

	Bool FilePackage::ReadAllFileInfo()
	{
		// Open the package file
		if (!OpenPackageFile())
			return false;

		// Set the stream back to the start
		m_PackageStream.seekg(0, ios::beg);

		// Read the amount of characters for the file name
		// and make sure that it is the same size as when
		// the package was compiled
		UInt32 localNameLength = 0;
		m_PackageStream.read((char*) &localNameLength, sizeof(UInt32));
		ASSERT(localNameLength == FilePackage::NameLength);

		// Read the amount of files
		UInt32 fileCount = 0;
		m_PackageStream.read((char*)&fileCount, sizeof(UInt32));
		ASSERT(fileCount > 0);

		// Read the file infos
		for (UInt32 i = 0; i < fileCount; ++i)
		{
			File* lpFile = ReadFileInfo();
			ASSERT(lpFile);
			if (!lpFile)
				return false;

			m_Files.insert(make_pair(lpFile->GetName(), lpFile));
		}

		// Close the package file
		ClosePackageFile();

		return true;
	}
	File* FilePackage::ReadFileInfo()
	{
		TChar name[FilePackage::NameLength];
		UInt64 dataStart = 0;
		UInt64 dataSize = 0;

		m_PackageStream.read((char*)name, FilePackage::NameLength * sizeof(TChar));
		m_PackageStream.read((char*)&dataStart, sizeof(UInt64));
		m_PackageStream.read((char*)&dataSize, sizeof(UInt64));

		ASSERT(dataStart > 0);
		ASSERT(dataSize > 0);

		return new File(this, tstring(name), dataStart, dataSize);
	}


	Bool FilePackage::OpenPackageFile()
	{
		m_PackageStream.open(m_Path.c_str(), ios::in | ios::binary);
		ASSERT(m_PackageStream);
		if (!m_PackageStream)
		{
			Log::WriteLine("Could not open file \"%s\".", m_Path.c_str());
			return false;
		}

		return true;
	}
	void FilePackage::ClosePackageFile()
	{
		ASSERT(m_PackageStream);
		ASSERT(m_PackageStream.is_open());

		m_PackageStream.close();
	}

	void FilePackage::SetPosition(Size_T position)
	{
		ASSERT(m_PackageStream);
		ASSERT(m_PackageStream.is_open());

		m_PackageStream.seekg(position, ios::beg);
	}
	void FilePackage::Read(void* lpData, Size_T dataSize)
	{
		ASSERT(m_PackageStream);
		ASSERT(m_PackageStream.is_open());

		m_PackageStream.read((char*)lpData, dataSize);
	}

	File* FilePackage::GetFile(const tstring& file) const
	{
		ASSERT(ContainsFile(file));
		return m_Files.at(file);
	}

	Bool FilePackage::ContainsFile(const tstring& file) const
	{
		return m_Files.count(file) > 0;
	}

	const tstring& FilePackage::GetName() const
	{
		return m_Name;
	}
	const tstring& FilePackage::GetPath() const
	{
		return m_Path;
	}

}